use tracing::Level;
use tracing_subscriber::{fmt, layer::SubscriberExt, Layer, Registry, EnvFilter};
use tracing_appender::{non_blocking, rolling};
use std::path::PathBuf;

/// 日志配置
#[derive(Debug, Clone)]
pub struct LogConfig {
    pub level: Level,
    pub file_path: Option<PathBuf>,
    pub max_files: usize,
    pub max_file_size: u64,
    pub enable_console: bool,
}

impl Default for LogConfig {
    fn default() -> Self {
        Self {
            level: Level::INFO,
            file_path: None,
            max_files: 10,
            max_file_size: 100 * 1024 * 1024, // 100MB
            enable_console: true,
        }
    }
}

/// 日志服务
pub struct LoggerService {
    config: LogConfig,
}

impl LoggerService {
    pub fn new(config: LogConfig) -> Self {
        Self { config }
    }

    /// 初始化日志系统
    pub fn init(&self) -> anyhow::Result<()> {
        // 创建环境过滤器
        let env_filter = EnvFilter::new(match self.config.level {
            Level::TRACE => "trace",
            Level::DEBUG => "debug",
            Level::INFO => "info",
            Level::WARN => "warn",
            Level::ERROR => "error",
        });

        let mut layers = Vec::new();

        // 控制台输出层
        if self.config.enable_console {
            let console_layer = fmt::layer()
                .with_target(false)
                .with_level(true)
                .with_thread_ids(true)
                .with_thread_names(true)
                .compact();
            layers.push(console_layer.boxed());
        }

        // 文件输出层
        if let Some(file_path) = &self.config.file_path {
            let file_appender = rolling::Builder::new()
                .rotation(tracing_appender::rolling::Rotation::HOURLY)
                .max_log_files(self.config.max_files)
                .filename_prefix("gateway")
                .filename_suffix("log")
                .build(file_path)?;

            let (non_blocking, _guard) = non_blocking(file_appender);
            let file_layer = fmt::layer()
                .with_writer(non_blocking)
                .with_ansi(false)
                .with_target(true)
                .with_level(true)
                .with_thread_ids(true)
                .with_thread_names(true)
                .compact();
            layers.push(file_layer.boxed());
        }

        // 注册日志系统
        let subscriber = Registry::default()
            .with(env_filter)
            .with(layers);

        tracing::subscriber::set_global_default(subscriber)?;

        Ok(())
    }

    /// 记录结构化日志
    pub fn log_structured(&self, level: Level, message: &str, fields: &[(&str, &str)]) {
        match level {
            Level::TRACE => tracing::trace!(message, fields = ?fields),
            Level::DEBUG => tracing::debug!(message, fields = ?fields),
            Level::INFO => tracing::info!(message, fields = ?fields),
            Level::WARN => tracing::warn!(message, fields = ?fields),
            Level::ERROR => tracing::error!(message, fields = ?fields),
        }
    }

    /// 记录请求日志
    pub fn log_request(&self, method: &str, path: &str, status: u16, duration: u64, client_ip: &str) {
        let fields = [
            ("method", method),
            ("path", path),
            ("status", &status.to_string()),
            ("duration_ms", &duration.to_string()),
            ("client_ip", client_ip),
        ];

        if status >= 400 {
            self.log_structured(Level::WARN, "HTTP请求处理完成", &fields);
        } else {
            self.log_structured(Level::INFO, "HTTP请求处理完成", &fields);
        }
    }

    /// 记录认证日志
    pub fn log_auth(&self, username: &str, action: &str, success: bool, client_ip: &str) {
        let status = if success { "成功" } else { "失败" };
        let level = if success { Level::INFO } else { Level::WARN };

        let fields = [
            ("username", username),
            ("action", action),
            ("status", status),
            ("client_ip", client_ip),
        ];

        self.log_structured(level, &format!("认证操作: {}", action), &fields);
    }

    /// 记录系统事件
    pub fn log_system_event(&self, event: &str, details: &str) {
        let fields = [("event", event), ("details", details)];
        self.log_structured(Level::INFO, "系统事件", &fields);
    }
}

/// 全局日志实例
pub static LOGGER: once_cell::sync::OnceCell<LoggerService> = once_cell::sync::OnceCell::new();

/// 初始化全局日志
pub fn init_global_logger(config: LogConfig) -> anyhow::Result<()> {
    let logger = LoggerService::new(config);
    logger.init()?;
    LOGGER.set(logger).map_err(|_| anyhow::anyhow!("Logger already initialized"))?;
    Ok(())
}

/// 获取全局日志实例
pub fn get_logger() -> &'static LoggerService {
    LOGGER.get().expect("Logger not initialized")
}